﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Collections;
using System.Diagnostics;
using System.Reflection;

namespace LoungeWare
{
    public partial class MovieExplorer : Form
    {
        #region Private member variables
        LVSort m_lvSort = new LVSort();

        #endregion

        #region CTOR
        private MovieExplorer()
        {
            InitializeComponent();
        }

        private static MovieExplorer m_Form = null;
        public static MovieExplorer Instance
        {
            get
            {
                if (m_Form == null)
                    m_Form = new MovieExplorer();
                return m_Form;
            }
        }

        #endregion

        #region OnLoad / Load movies
        private void MovieExplorer_Load(object sender, EventArgs e)
        {
            this.Text = string.Format("Movie Explorer v{0}", Assembly.GetExecutingAssembly().GetName().Version);
            _List.ListViewItemSorter = m_lvSort;
        }

        private void OnLoad()
        {
            _List.Items.Clear();
            MovieLoader loader = new MovieLoader(_FolderBrowser.SelectedPath);
            loader.RunWorkerCompleted += new RunWorkerCompletedEventHandler(loader_RunWorkerCompleted);
            loader.RunWorkerAsync();
            _MenuStrip.Enabled = false;
            Cursor = Cursors.WaitCursor;
        }

        void loader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            OnFormReady();
        }

        private void OnFormReady()
        {
            _MenuStrip.Enabled = true;
            Cursor = Cursors.Default;
            SetStatusLabel("Ready");
            SetStatusProgress(2, 1);
        }
        #endregion

        #region Public UI methods (thread safe)
		// This delegate enables asynchronous calls from other threads
        delegate void AddListItem(ListViewItem item);
        public void AddList(ListViewItem item)
        {
            if (_List.InvokeRequired)
            {    

                AddListItem addlist = new AddListItem(AddList);
                this.Invoke(addlist, new object[] { item });
            }
            else
            {
                _List.Items.Add(item);
                _List.Refresh();
            }
        }

        // This delegate enables asynchronous calls from other threads
        delegate void SetStatusProgressFunc(int nCurrent, int nFiles);
        public void SetStatusProgress(int nCurrent, int nFiles)
        {
            if (_List.InvokeRequired)
            {

                SetStatusProgressFunc addlist = new SetStatusProgressFunc(SetStatusProgress);
                this.Invoke(addlist, new object[] { nCurrent, nFiles });
            }
            else
            {
                _StatusItemProgressBar.Step = 1;
                _StatusItemProgressBar.Value = nCurrent;
                _StatusItemProgressBar.Maximum = nFiles;
                _StatusItemProgressBar.Visible = (nCurrent <= nFiles);

                _StatusItemProgressText.Text = string.Format("{0} of {1}", nCurrent, nFiles);
                _StatusItemProgressText.Visible = (nCurrent <= nFiles);
                _StatusStrip.Refresh();
            }
        }

        // This delegate enables asynchronous calls from other threads
        delegate void SetStatusLabelFunc(string sStatus);
        public void SetStatusLabel(string sStatus)
        {
            if (_List.InvokeRequired)
            {

                SetStatusLabelFunc addlist = new SetStatusLabelFunc(SetStatusLabel);
                this.Invoke(addlist, new object[] { sStatus });
            }
            else
            {
                _StatusItemLabel.Text = sStatus;
                _StatusStrip.Refresh();
            }
        }
	    #endregion    

        #region Events
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (_FolderBrowser.ShowDialog() == DialogResult.OK)
            {
                OnLoad();
            }
        }

        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OnLoad();
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            List<string> lFiles = new List<string>();
            foreach (ListViewItem item in _List.Items)
            {
                if (item.Checked)
                    lFiles.Add(item.Tag.ToString());
            }

            if (lFiles.Count == 0)
            {
                MessageBox.Show("No movies selected!");
                return;
            }

            if (_FolderBrowser.ShowDialog() == DialogResult.OK)
            {
                MovieCopy copy = new MovieCopy(lFiles, _FolderBrowser.SelectedPath);
                copy.RunWorkerCompleted += new RunWorkerCompletedEventHandler(copy_RunWorkerCompleted);
                copy.RunWorkerAsync();
                _MenuStrip.Enabled = false;
                Cursor = Cursors.WaitCursor;
            }
        }

        void copy_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            OnFormReady();
        }

        private void _List_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            if (e.Column == m_lvSort.ColumnToSort)
            {
                // Reverse the current sort direction for this column.
                if (m_lvSort.OrderOfSort == SortOrder.Ascending)
                    m_lvSort.OrderOfSort = SortOrder.Descending;
                else
                    m_lvSort.OrderOfSort = SortOrder.Ascending;
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                m_lvSort.ColumnToSort = e.Column;
                m_lvSort.OrderOfSort = SortOrder.Ascending;
            }
            _List.Sort();
        }

        #endregion
    }

    #region List View Sort class
    public class LVSort : IComparer
    {
        public int ColumnToSort { get; set; }
        public SortOrder OrderOfSort { get; set; }
        private CaseInsensitiveComparer ObjectCompare = new CaseInsensitiveComparer();

        #region IComparer Members

        public int Compare(object x, object y)
        {
            int compareResult;
            ListViewItem listviewX, listviewY;

            // Cast the objects to be compared to ListViewItem objects
            listviewX = (ListViewItem)x;
            listviewY = (ListViewItem)y;

            // Compare the two items
            compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);

            // Calculate correct return value based on object comparison
            if (OrderOfSort == SortOrder.Ascending)
            {
                // Ascending sort is selected, return normal result of compare operation
                return compareResult;
            }
            else if (OrderOfSort == SortOrder.Descending)
            {
                // Descending sort is selected, return negative result of compare operation
                return (-compareResult);
            }
            else
            {
                // Return '0' to indicate they are equal
                return 0;
            }
        }

        #endregion
    } 
    #endregion
}
